#pragma once
#ifndef SCRIPT__EDITOR__WIDGET__HH__
#define SCRIPT__EDITOR__WIDGET__HH__

#include <qboxlayout.h>
#include <qplaintextedit.h>
#include <qtabwidget.h>
#include <qsyntaxhighlighter.h>
#include <map>
#include <qlistwidget.h>

#include "ScriptEditorPrereqs.h"

namespace Lit
{
	namespace Editor
	{
		struct ScriptSyntaxPolice
		{
			ScriptSyntaxPolice(){}
			ScriptSyntaxPolice( const std::string &police_name, const int weight=10, const QColor& color = QColor(Qt::black), bool underline = false, bool italic = false )
			{
				format.setForeground(color);
				format.setFontFamily( QString(police_name.c_str()) );
				format.setFontWeight( weight );
				format.setFontUnderline( underline );
				format.setFontItalic( italic );
			}
			ScriptSyntaxPolice( const ScriptSyntaxPolice& rk )
				: format( rk.format )
			{
			}
			QTextCharFormat format;
		};
		struct ScriptSyntaxRule
		{
			ScriptSyntaxRule(){}
			ScriptSyntaxRule( const std::string &pattern, const ScriptSyntaxPolice& police_ )
				: pattern( QString(pattern.c_str()) )
				, police( police_)
			{
			}
			ScriptSyntaxRule( const ScriptSyntaxRule& rk )
				: pattern( rk.pattern )
				, police( rk.police )
			{
			}
			QRegExp pattern;
			ScriptSyntaxPolice police;
		};
		class ScriptHighlighter : public QSyntaxHighlighter
		{
			Q_OBJECT

		public:
			ScriptHighlighter(QTextDocument *parent = 0);

		protected:
			void highlightBlock(const QString &text);

			
		private:
			QVector<ScriptSyntaxRule> highlightingRules;

			QRegExp commentStartExpression;
			QRegExp commentEndExpression;

			ScriptSyntaxPolice keywordFormat;
			ScriptSyntaxPolice classFormat;
			ScriptSyntaxPolice singleLineCommentFormat;
			ScriptSyntaxPolice multiLineCommentFormat;
			ScriptSyntaxPolice quotationFormat;
			ScriptSyntaxPolice functionFormat;
		};
		class ScriptEditorMarginWidget : public QWidget
		{
		public:
			ScriptEditorMarginWidget(ScriptEditorWidget *edt);
			virtual ~ScriptEditorMarginWidget();

			QSize sizeHint() const;

		protected:
			void paintEvent(QPaintEvent *event);

		private:
			ScriptEditorWidget *mEditor;
		};

		class ScriptEditorCompleter : public QListWidget
		{
			Q_OBJECT

		protected:
			QStringList mWords;
			ScriptEditorWidget* mEditor;

		public:
			ScriptEditorCompleter(ScriptEditorWidget*editor);
			~ScriptEditorCompleter( );
			
			void hide();
			void show( QPoint pos );

			bool eventFilter( QObject * obj, QEvent * evt );

			void keyPressEvent( QKeyEvent * evt );
			bool hasKeyword( const QString &word ) const;
			void addKeywords( const QStringList& words );
			void showCompletion( const std::string &word );

		protected slots:
			void complete( QListWidgetItem* itm );
		};
		class ScriptEditorWidget : public QPlainTextEdit
		{
			Q_OBJECT
			
		protected:
			friend class ScriptEditorMarginWidget;

		protected:
			size_t				mId;
			InstancePtr			mInstance;
			FilePath			mPath;
			ScriptTabWidget *	mTabWidget;
			QFont				mDefaultFont;
			ScriptHighlighter*	mHighlighter;

			void	resizeEvent(QResizeEvent *evt);
			
			void	lineNumberAreaPaintEvent(QPaintEvent *evt);
			int		lineNumberAreaWidth();

		private slots:
			void	updateLineNumberAreaWidth(int newBlockCount);
			void	highlightCurrentLine();
			void	updateLineNumberArea(const QRect &, int);

		protected:
			ScriptEditorMarginWidget *	mMargin;
			ScriptEditorCompleter *		mCompleter;
		public:
			ScriptEditorWidget( InstancePtr inst, ScriptTabWidget * parent = NULL );
			~ScriptEditorWidget();
			
			ScriptEditorCompleter *				getCompleter();
			const ScriptEditorCompleter *		getCompleter() const;

			void showCompletion( const std::string &word );

			void indentSelection();
			void unindentSelection();

			size_t getIndentation() const;
			void paintEvent( QPaintEvent * evt );

			void keyPressEvent( QKeyEvent * evt );
			bool isModified() const;
			void setModified( bool state );
			
			void setFont( const QFont &font ){ QPlainTextEdit::setFont( font ); }
			QFont getFont( ) const{ return QPlainTextEdit::font(); }
			const QFont& getDefaultFont( ) const{ return mDefaultFont; }
			
			std::string getName( bool ext = true ) const;

			FilePath getPath() const;
			void setPath( const FilePath& path );

			void saveScript( );
			void saveScriptAs( );
			void loadScript( );

			void setText( const std::string &txt );
			std::string getText() const;

			void setId(size_t id){mId=id;}
			size_t getId() const;
			
		protected slots:
			void modifiedStateChanged(bool);
		signals:
			void modifiedStateChanged(ScriptEditorWidget *, bool);
		};

	};
}

#endif